package com.foftact.stockpe.service.impl;

import com.foftact.stockpe.StockPE;
import com.foftact.stockpe.mapper.StockPEMapper;
import com.foftact.stockpe.service.StockPEService;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 股票财务分析数据服务实现类
 */
@Service("stockPEService")
public class StockPEServiceImpl implements StockPEService {

    private static final Logger logger = LoggerFactory.getLogger(StockPEServiceImpl.class);
    private static final String DATA_SOURCE = "eastmoney"; // 东方财富网
    private static final String BASE_URL = "https://emweb.securities.eastmoney.com/pc_hsf10/pages/index.html?type=web&code=%s&color=b#/cpbd";
    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Autowired
    private StockPEMapper stockPEMapper;

    @Override
    @Transactional
    public int fetchAndSaveStockPEData() {
        logger.info("开始抓取股票财务分析数据，时间：{}", sdf.format(new Date()));
        int result = 0;
        try {
            // 模拟抓取部分股票数据
            // 实际项目中应该从股票列表中获取需要抓取的股票代码
            String[] stockCodes = {
                "SZ000063", // 中兴通讯
                "SZ003009", // 中天火箭
                "SZ000002", // 万科A
                "SZ000858", // 五粮液
                "SZ000001"  // 平安银行
            };

            List<StockPE> stockPEList = new ArrayList<>();
            for (String stockCode : stockCodes) {
                try {
                    StockPE stockPE = fetchStockPEFromWeb(stockCode);
                    if (stockPE != null) {
                        stockPEList.add(stockPE);
                    }
                } catch (Exception e) {
                    logger.error("抓取股票[{}]财务数据失败", stockCode, e);
                }
            }

            // 批量保存数据
            if (!stockPEList.isEmpty()) {
                result = batchSaveStockPE(stockPEList);
            }

            // 删除超过1年的旧数据
            deleteOldData(365);
            logger.info("股票财务分析数据抓取保存成功，数量：{}", result);
        } catch (Exception e) {
            logger.error("抓取股票财务分析数据失败", e);
            throw new RuntimeException("抓取股票财务分析数据失败", e);
        }
        return result;
    }

    private StockPE fetchStockPEFromWeb(String stockCode) throws Exception {
        // 构建完整URL
        String url = String.format(BASE_URL, stockCode);
        logger.info("开始抓取股票[{}]财务数据，URL：{}", stockCode, url);

        try {
            // 实际项目中使用Jsoup连接网页
            // Document doc = Jsoup.connect(url).timeout(10000).get();
            
            // 这里返回模拟数据以便测试
            return generateMockStockPE(stockCode);
        } catch (Exception e) {
            logger.error("抓取股票[{}]财务数据异常，返回模拟数据", stockCode, e);
            return generateMockStockPE(stockCode);
        }
    }

    private StockPE generateMockStockPE(String stockCode) {
        StockPE stockPE = new StockPE();
        stockPE.setSecurityCode(stockCode.substring(2)); // 去掉市场代码前缀
        stockPE.setSecurityName(getMockStockName(stockCode));
        stockPE.setTradeDate(new Date());
        stockPE.setIndicatorType("FINANCIAL_ANALYSIS");
        
        // 随机生成一些财务数据
        double peValue = 10 + Math.random() * 40;
        stockPE.setPeTTM(new BigDecimal(String.format("%.2f", peValue)));
        
        double roeValue = 5 + Math.random() * 20;
        stockPE.setRoeTTM(new BigDecimal(String.format("%.2f", roeValue)));
        
        stockPE.setRoeTTMLast2(new BigDecimal(String.format("%.2f", roeValue * 0.95)));
        stockPE.setRoeTTMLast5(new BigDecimal(String.format("%.2f", roeValue * 0.85)));
        stockPE.setRoeTTMQuarterly(new BigDecimal(String.format("%.2f", 1.0 + Math.random() * 0.5)));
        stockPE.setRoeTTMYearly(new BigDecimal(String.format("%.2f", 1.0 + Math.random() * 0.3)));
        
        // 设置8个季度的ROE数据
        for (int i = 1; i <= 8; i++) {
            double rate = 1.5 + Math.random() * 3.0;
            String date = String.format("202%dQ%d", (i <= 4 ? 3 : 2), (i <= 4 ? 5 - i : 9 - i));
            
            switch (i) {
                case 1: stockPE.setRoeLast1Rate(new BigDecimal(String.format("%.2f", rate))); stockPE.setRoeLast1Date(date); break;
                case 2: stockPE.setRoeLast2Rate(new BigDecimal(String.format("%.2f", rate))); stockPE.setRoeLast2Date(date); break;
                case 3: stockPE.setRoeLast3Rate(new BigDecimal(String.format("%.2f", rate))); stockPE.setRoeLast3Date(date); break;
                case 4: stockPE.setRoeLast4Rate(new BigDecimal(String.format("%.2f", rate))); stockPE.setRoeLast4Date(date); break;
                case 5: stockPE.setRoeLast5Rate(new BigDecimal(String.format("%.2f", rate))); stockPE.setRoeLast5Date(date); break;
                case 6: stockPE.setRoeLast6Rate(new BigDecimal(String.format("%.2f", rate))); stockPE.setRoeLast6Date(date); break;
                case 7: stockPE.setRoeLast7Rate(new BigDecimal(String.format("%.2f", rate))); stockPE.setRoeLast7Date(date); break;
                case 8: stockPE.setRoeLast8Rate(new BigDecimal(String.format("%.2f", rate))); stockPE.setRoeLast8Date(date); break;
            }
        }
        
        stockPE.setCreateTime(new Date());
        stockPE.setUpdateTime(new Date());
        
        return stockPE;
    }

    private String getMockStockName(String stockCode) {
        switch (stockCode) {
            case "SZ000063": return "中兴通讯";
            case "SZ003009": return "中天火箭";
            case "SZ000002": return "万科A";
            case "SZ000858": return "五粮液";
            case "SZ000001": return "平安银行";
            default: return "股票" + stockCode.substring(2);
        }
    }

    @Override
    @Transactional
    public int saveStockPE(StockPE stockPE) {
        if (stockPE == null) {
            logger.warn("保存的股票财务数据为空");
            return 0;
        }
        
        try {
            // 设置创建和更新时间
            if (stockPE.getCreateTime() == null) {
                stockPE.setCreateTime(new Date());
            }
            stockPE.setUpdateTime(new Date());
            
            // 检查是否已存在该股票数据
            StockPE existing = stockPEMapper.selectBySecurityCode(stockPE.getSecurityCode());
            if (existing != null) {
                return stockPEMapper.updateByCodeAndTradeDate(stockPE);
            } else {
                return stockPEMapper.insert(stockPE);
            }
        } catch (Exception e) {
            logger.error("保存股票财务数据失败", e);
            throw new RuntimeException("保存股票财务数据失败", e);
        }
    }

    @Override
    @Transactional
    public int batchSaveStockPE(List<StockPE> stockPEList) {
        if (stockPEList == null || stockPEList.isEmpty()) {
            logger.warn("批量保存的股票财务数据为空");
            return 0;
        }
        
        try {
            Date now = new Date();
            for (StockPE stockPE : stockPEList) {
                if (stockPE.getCreateTime() == null) {
                    stockPE.setCreateTime(now);
                }
                stockPE.setUpdateTime(now);
            }
            
            return stockPEMapper.batchInsert(stockPEList);
        } catch (Exception e) {
            logger.error("批量保存股票财务数据失败", e);
            throw new RuntimeException("批量保存股票财务数据失败", e);
        }
    }

    @Override
    public StockPE getStockPEBySecurityCode(String securityCode) {
        if (securityCode == null || securityCode.trim().isEmpty()) {
            logger.warn("查询的证券代码为空");
            return null;
        }
        
        try {
            return stockPEMapper.selectBySecurityCode(securityCode);
        } catch (Exception e) {
            logger.error("查询股票财务数据失败，代码：{}", securityCode, e);
            throw new RuntimeException("查询股票财务数据失败", e);
        }
    }

    @Override
    public List<StockPE> getAllStockPEs() {
        try {
            return stockPEMapper.selectAll();
        } catch (Exception e) {
            logger.error("查询所有股票财务数据失败", e);
            throw new RuntimeException("查询所有股票财务数据失败", e);
        }
    }

    @Override
    @Transactional
    public int deleteOldData(int days) {
        if (days <= 0) {
            logger.warn("删除天数必须大于0");
            return 0;
        }
        
        try {
            int result = stockPEMapper.deleteOldData(days);
            logger.info("删除超过{}天的股票财务数据，删除条数：{}", days, result);
            return result;
        } catch (Exception e) {
            logger.error("删除旧数据失败", e);
            throw new RuntimeException("删除旧数据失败", e);
        }
    }
}